﻿package cn.ac.cintcm.prespring.tree;

import java.io.BufferedWriter;
import java.io.FileWriter;
import java.io.IOException;
import java.util.HashMap;
import java.util.List;

import cn.ac.cintcm.prespring.util.Config;
import cn.ac.cintcm.prespring.util.FileUtil;
import cn.ac.cintcm.prespring.util.IndexFile;
import cn.ac.cintcm.prespring.util.NameIndex;
import cn.ac.cintcm.prespring.util.StringUtil;


public class WebTree {
    static final String LIST_BEGIN = "<table class=\"stats\">";
    static final String ROW_BEGIN = "<tr><td>";
    static final String ROW_END = "</td></tr>";
    static final String LIST_END = "</table>";
    private NameIndex elements;
    private NameIndex items;
    private int rootId;
    private String rootName;
    private IndexFile index;
    private String template = "template.txt";
    private VisitMemory vm;
    private String url ="''";
    private String title="''";
    private String target="''";
    private String icon="''";
    private String link;

    public WebTree(String elementsFile, String itemsFile) throws IOException {
        elements = new NameIndex(elementsFile);
        items = new NameIndex(itemsFile);
    }
    
    public WebTree(NameIndex elements, NameIndex items) throws IOException {
        this.elements = elements;
        this.items = items;
    }
    
    public void setIndex(int id, IndexFile index) {
        this.rootId = id;
        this.index = index;
    }
    
    protected String getTitle(int id) {
        rootName = items.getIdName().get(id);
        return rootName;
    }
    
    protected void setJavaScript(String js) {
    }
    
    public void setTree(VisitMemory vm) {
        this.vm = vm;
    }

    public void createWebTree(String fileName) throws IOException {
        BufferedWriter writer = new BufferedWriter(new FileWriter(fileName));
        writer.write(createWebTree().toString());
        writer.close();
    }
    
    public StringBuilder createWebTree() throws IOException {
        List<String> templateStrList = FileUtil.read(template);
        return createWebTree(templateStrList);
    }
 
    public StringBuilder createWebTree(List<String> templateStrList) throws IOException {
        StringBuilder treeStr = new StringBuilder();
        String treeContent = printTree().toString();
        for (String s : templateStrList) {
            if (s.equals("$title")) {
                treeStr.append(getTitle(rootId));
            } else if (s.equals("$treebody")) {
                treeStr.append(treeContent);
            } else {
                treeStr.append(s);
            }
            treeStr.append(Config.NEW_LINE);
        }
        return treeStr;
    }

    /**
     * ���������������������������������JS���������������
     * (id, parentId, url, title, target, icon, iconName)
     * @throws IOException
     */
    public StringBuffer printTree() {
        StringBuffer writer = new StringBuffer();
        writer.append(TreeStyle.print(TreeStyle.VERTICAL, "minus", printMinusTree()));
        writer.append(TreeStyle.print(TreeStyle.VERTICAL, "plus", printPlusTree()));
        return writer;
    }
    
    /**
     * ���������������������������JS������������������������������������������
     * @return
     */
    public StringBuffer printPlusTree() {
        StringBuffer writer = new StringBuffer();
        if (vm != null) {
            //������������������������, -2������������������-1���������������������
            plusPrint(rootId, -2, writer);
            
            String node = createRootNode(rootId);  

            writer.append("-2" + rootId + ",-1,'" + node 
                    + "'," + url + "," + title + "," + target + "," + icon + ",'增药'");
            writer.append(Config.NEW_LINE);
        }
        return writer;
            
    }
    
    /**
     * ���������������������������JS������������������������������������������
     * @return 
     */
    public StringBuffer printMinusTree() {
        StringBuffer writer = new StringBuffer();
        if (vm != null) {
            minusPrint(rootId, 0, writer);
            
            String node = createRootNode(rootId);    
            //������������������������
            writer.append("0" + rootId + ",-1,'" + node 
                    + "'," + url + "," + title + "," + target + "," + icon + ",'减药'");
            writer.append(Config.NEW_LINE);
        }
        return writer;
    }    
    /**
     * ������������������
     * @param pres ���������������������������
     * @param minusHerb ������������������������
     * @param writer ���������������������
     */
    private void minusPrint(int pres, int minusHerb, StringBuffer writer) {
        //������������������������������������������
        List<Integer>  hbs = index.getIdListIndex().get(pres);
        if (hbs == null) {
            return;
        }
        int count = hbs.size();
        //������������������������������������������������������������������������������
        HashMap<Integer, List<MemoryNode>> rsMap = vm.getLadder().get(count - 1);
        if (rsMap == null) {
            return;
        }
        StringBuilder sb = new StringBuilder();
        //������������������������������������������������������������������������������������
        for (Integer h : hbs) {
            List<MemoryNode> ps = rsMap.get(h);
            int id = 0;
            sb.setLength(0);
            if (ps != null) {
                sb.append(LIST_BEGIN);
                //���������������������������������������������������������������������������
                for (MemoryNode p : ps) {
                    if (p.getParent() == pres) {
                        if (p.getChild() > id) {
                            id = p.getChild();
                        }
                        createNode(p.getChild(), sb);
                    }
                }
                sb.append(LIST_END);      
                writer.append(h+""+id + "," + minusHerb + "" + pres + ",'" + sb.toString() 
                        + "'," + url + "," + title + "," + target + "," + icon + ",'" 
                        + elements.getIdName().get(h)+h +"'");
                writer.append(Config.NEW_LINE);
            //���������������������������������������������������������������������������
            } else {
                writer.append(minusHerb + "" +h + "0," + minusHerb + "" + pres + ",'" + sb.toString() 
                        + "'," + url + "," + title + "," + target + "," + icon + ",'" 
                        + elements.getIdName().get(h)+h +"'");
                writer.append(Config.NEW_LINE);
            }
            if (id != 0) {
                minusPrint(id, h, writer);
            }
        }   
     }
    
    /**
     * ������������������
     * @param pres ���������������������������id���
     * @param plusHerb ���������������id������
     * @param writer ���������JS������������������
     */
    private void plusPrint(int pres, int plusHerb, StringBuffer writer) {
        //������������������������������������������������
        List<Integer>  hbs = index.getIdListIndex().get(pres);
        if (hbs == null) {
            return;
        }
        int count = hbs.size();
        //���������������������������������������������������������������������
        HashMap<Integer, List<MemoryNode>> rsMap = vm.getLadder().get(count + 1);
        if (rsMap == null) {
            return;
        }
        StringBuilder sb = new StringBuilder();
        //���������������������������������������������������������������������������������������������������������������
        for (Integer h : rsMap.keySet()) {
            List<MemoryNode> ps = rsMap.get(h);
            int id = 0;
            sb.setLength(0);
            if (ps != null) {
                boolean haveChild = false;
                //������������������������h���������������������������
                for (MemoryNode n : ps) {
                    //���������������������������������������������������������������
                    if (n.getParent() == pres) {
                        //������������������������������
                        if (!haveChild) {
                            haveChild = true;
                            sb.append(LIST_BEGIN);
                        }
                        //���������������������������������������������������������������id������������������������
                        if (n.getChild() > id) {
                            id = n.getChild();
                        }
                        createNode(n.getChild(), sb);
                    }
                }
                
                if (haveChild) {
                    sb.append(LIST_END);      
                    writer.append(h + "" + id + "," + plusHerb + "" + pres + ",'" + sb.toString() 
                            + "'," + url + "," + title + "," + target + "," + icon + ",'" 
                            + elements.getIdName().get(h)+h +"'");
                    writer.append(Config.NEW_LINE);
                }
            }
            if (id != 0) {
                plusPrint(id, h, writer);
            }
        }   
    }    
    private String createRootNode(int p) {
        StringBuilder sb = new StringBuilder();
        sb.append(LIST_BEGIN);
        createNode(p, sb);
        sb.append(LIST_END);      
        return sb.toString();
    }

    private void createNode(int p, StringBuilder sb) {
        sb.append(ROW_BEGIN);
        if (link != null) {
            sb.append("<a target=\"_blank\" href=\"");
            sb.append(link);
            sb.append(StringUtil.getId(p));
            sb.append("\">");
        }
        sb.append(items.getIdName().get(p));
        if (link != null) {
            sb.append("</a>");
        }
        sb.append(ROW_END);
    }

    public String getTemplate() {
        return template;
    }

    public void setTemplate(String template) {
        this.template = template;
    }
    
    public String getLink() {
        return link;
    }

    public void setLink(String link) {
        this.link = link;
    }    
}
